/**
 * @name: TheUpload
 * @description: 上传组件封装
 * @upTime: 2023--02--06
 * @props { bool }      disabled        是否显示上传控件
 * @props { number }    len             上传数量
 * @props { string }    label           上传按钮文字
 * @props { func }      getFileResult   图片上传回调
 * @props { string }    type            上传列表的内建样式，支持三种基本样式 text, picture 和 picture-card
 * @props { object }    data            上传所需额外参数或返回上传额外参数的方法
 * @props { string }    fileType        上传的文件格式     - 可选 video||image
 * @props { number }    maxSize         上传的文件大小     - 单位M
 * @props { number }    imgWidth        设置限制上传的图片宽度
 * @props { number }    imgHeight       设置限制上传的图片高度
 * @props { string }    mode            设置上传的图片模式  - 可选 ‘shop’
 * @props { array }     accept          控制上传的文件类型
 * @props { bool }      isConversion    是否开启转换jpg格式
 * @props { bool }      isShowRemoveIcon是否显示删除icon按钮
 * @props { array }      fileList        现有数据集合
 *
 **/

import React from 'react'
import PropTypes from 'prop-types'
import { Upload, Modal } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { withRouter } from 'react-router-dom'
import { getBase } from '@/utils/getBase'
import videoPng from '@/assets/images/video.png'
import Compressor from 'compressorjs';
import { includes } from 'lodash';

class TheUpload extends React.Component {
  state = {
    previewVisible: false,
    previewImage: '',
    previewTitle: '',
    fileList: [],
    previewType: 'img'
  };

  componentDidUpdate(prev) {
    if (prev && Array.isArray(prev.fileList) && prev.fileList.length !== this.props.fileList.length) {

      this.setState({ fileList: this.props.fileList })
    }
  }

  componentDidMount() {
    if (this.props.fileList) {
      this.setState({ fileList: this.props.fileList })
    }
  }

  handleCancel = () => this.setState({ previewVisible: false });
  handleRemove = (file) => {
    const index = this.state.fileList.indexOf(file)
    this.state.fileList.splice(index, 1)
    this.setState({
      fileList: this.state.fileList
    }, () => {
      this.props.getFileResult(this.state.fileList)
    })
  }
  handlePreview = async file => {
    const type = this.getFileType(file.url || file.name)
    if (type === 'video') {
      let url = file.url
      if (url && url.includes('?')) {
        url = url.split("?")[0]
      }
      this.setState({
        previewImage: url || file.response.data,
        previewVisible: true,
        previewTitle: file.name || file.url.substring(file.url.lastIndexOf('/') + 1),
        previewType: 'video'
      });
      return
    } else if (type === 'audio') {
      let url = file.url
      if (url && url.includes('?')) {
        url = url.split("?")[0]
      }
      this.setState({
        previewImage: url || file.response.data,
        previewVisible: true,
        previewTitle: file.name || file.url.substring(file.url.lastIndexOf('/') + 1),
        previewType: 'audio'
      });
      return
    } else {
      if (!file.url && !file.preview) {
        file.preview = await getBase(file.originFileObj);
      }
      this.setState({
        previewImage: file.url || file.preview,
        previewVisible: true,
        previewTitle: file.name || file.url.substring(file.url.lastIndexOf('/') + 1),
        previewType: 'img'
      });
    }

  };

  handleChange = ({ file, fileList, event }) => {

    console.log('---------fileList--------------', fileList);

    const { maxSize, fileType } = this.props
    if (fileType && !['video', 'image', 'audio'].includes(fileType)) {
      React.$message({
        type: 'warning',
        content: `fileType字段类型错误,仅支持image/video类型`
      })
      return
    }
    if (fileType && fileType === 'video') {
      if (file.type !== "video/mp4") return
    }
    if (fileType && fileType === 'image') {
      if (file.type && file.type !== "image/jpg" && file.type !== "image/jpeg" && file.type !== "image/png" && file.type !== "image/webp" && file.type !== "image/svg+xml") return
    }
    // if (file.type && file.type !== "image/jpg" && file.type !== "image/jpeg" && file.type !== "image/png" && file.type !== "video/mp4" && file.type !== "image/webp" && file.type !== "image/svg+xml") {
    //   return
    // }
    if (file.size / 1024 / 1024 >= (maxSize || 5)) {
      return
    }
    console.log('file:', file);

    if (file && fileList && fileList.length) {
      console.log(fileList, 'fileList');

      fileList = fileList.map(v => {
        // console.log(v)
        if (v.status === 'done' && v.response) {
          if (v.response && v.response.code === 0 && v.response.data) {
            return { ...v }
          } else {
            return {
              ...v,
              // uid: '-5',
              // name: v.name,
              status: 'error'
            }
          }
        } else if (v.status === 'error') {
          return {
            response: v.response,
            size: v.size,
            uid: '-5',
            name: v.name,
            status: 'error',
          }
        } else {
          return { ...v }
        }
      })
    }
    // console.log(fileList)
    //过滤数据大于10M的数据
    fileList = fileList.filter(v => (v.size / 1024 / 1024 < (maxSize || 5) || v.status === 'done'))
    this.props.getFileResult(fileList)
    this.setState({ fileList })
  };

  handlePreviewFile(file) {
    const that = this
    const fileType = this.getFileType(file.type)
    return new Promise((resolve) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = function (e) {
        const dataUrl = e.target.result;
        if (fileType === 'video') {
          resolve(that.getVideoCover(e.target.result))
        } else {
          resolve(dataUrl)
        }
      }
    })
  }

  // 获取视频封面
  getVideoCover = (src) => {
    return new Promise((resolve, reject) => {
      let video = document.createElement("video");
      video.setAttribute("src", src);
      video.setAttribute("autoplay", "autoplay");
      video.setAttribute("crossOrigin", "anonymous"); //设置跨域 否则toDataURL导出图片失败
      video.setAttribute("width", "300"); //设置大小，如果不设置，下面的canvas就要按需设置
      video.setAttribute("height", "200");
      video.currentTime = 1; //视频时长，一定要设置，不然大概率白屏
      video.addEventListener("loadeddata", function () {
        let canvas = document.createElement("canvas"),
          width = video.width, //canvas的尺寸和图片一样
          height = video.height;
        canvas.width = width; //画布大小，默认为视频宽高
        canvas.height = height;
        canvas.getContext("2d").drawImage(video, 0, 0, width, height); //绘制canvas
        let dataURL = canvas.toDataURL("image/png"); //转换为base64
        resolve(dataURL);
      });
    });
  }

  getFileType(str) {

    if (str.indexOf('mp4') > -1) {
      return 'video'
    } else if (str.indexOf('m4a') > -1 || str.indexOf('mp3') > -1) {
      return 'audio'
    } else {
      return 'image'
    }
  }

  // 把image 转换为 canvas对象
  imgToCanvas(image) {
    let canvas = document.createElement("canvas");
    canvas.width = image.width;
    canvas.height = image.height;
    canvas.getContext("2d").drawImage(image, 0, 0);
    return canvas;
  }

  //  canvas转换为image
  canvasToImg(canvas, type = 'jpeg') {
    return new Promise((resolve, reject) => {
      // 压缩
      canvas.toDataURL('image/jpeg', 0.9);
      canvas.toBlob((image) => {
        resolve(image)
      }, `image/${type}`)
    })
  }

  async imgTypeChange(file, image) {
    // 获取图片信息
    let imgName = file.name.split('.')[0]
    // 把image 转换为 canvas对象
    const can = this.imgToCanvas(image)
    // canvas转换为Bolb 类型image
    const blobImg = await this.canvasToImg(can, 'jpeg')
    return new Promise((resolve) => {
      resolve(new File([blobImg], `${imgName}.jpg`, { type: blobImg.type }))
    })
  }

  drawWaterMark({ img, textArray, fontFamily = "microsoft yahei", fontSize = 33, fontcolor = "#dadbdc", rotate = 30, textAlign = "left", density = 2.0 }) {

  }
  checkImageDimensions(file, maxWidth, maxHeight) {
    return new Promise((resolve, reject) => {
      // 检查文件是否为图片
      if (!file.type.startsWith('image/')) {
        reject(new Error('文件不是图片类型'));
      }

      const reader = new FileReader();
      reader.onload = (event) => {
        const image = new Image();
        image.onload = () => {
          if (image.width > maxWidth || image.height > maxHeight) {
            reject(new Error('图片尺寸超出限制'));
          } else {
            resolve();
          }
        };
        image.onerror = () => {
          reject(new Error('无法加载图片'));
        };
        image.src = event.target.result;
      };
      reader.onerror = () => {
        reject(new Error('文件读取出错'));
      };
      reader.readAsDataURL(file);
    });
  }
  render() {
    const { previewVisible, previewImage, fileList, previewTitle, previewType } = this.state;
    const {
      len,
      disabled,
      label,
      type,
      data,
      imgWidth,
      imgHeight,
      mode,
      fileType,
      maxSize,
      accept,
      isConversion,
      isShowRemoveIcon,
      drawWaterMark,
      markText
    } = this.props;
    const uploadButton = (
      <div>
        <PlusOutlined />
        <div style={{ marginTop: 8 }}>{label}</div>
      </div>
    );
    const checkFileSize = (file) => {
console.log('----file----',file);
      if (fileType && !['video', 'image', 'audio'].includes(fileType)) {
        React.$message({
          type: 'warning',
          content: `fileType字段类型错误,仅支持image/video类型`
        })
        return false || Upload.LIST_IGNORE;
      }

      if (!accept.filter(item => item.indexOf(fileType) !== -1).includes(file.type)) {
        // eslint-disable-next-line array-callback-return
        let mess = []
        // eslint-disable-next-line array-callback-return
        accept.filter(item => {
          if (item.indexOf(fileType) !== -1) {
            mess.push(item = item.replace(new RegExp(`${fileType}/`, 'g'), '.'))
          }
        })
        React.$message({
          type: 'warning',
          content: `${file.name} 不是 ${mess} 类型文件`
        })
        return false || Upload.LIST_IGNORE;
      }
      let _that = this;

      if (file.size / 1024 / 1024 < (maxSize || 5)) {
        return new Promise((resolve, reject) => {
          const width = parseInt(imgWidth) || Infinity;
          const height = parseInt(imgHeight) || Infinity;
          if (file.type === 'video/mp4') {
            const video = document.createElement('video')
            let reader = new FileReader();
            reader.readAsDataURL(file);
            // console.log(file, 'file');
            reader.onload = function (e) {
              // console.log(e.target.result);
              video.src = e.target.result;
              resolve();
            }
          } else if (file.type === 'audio/x-m4a' || file.type === 'audio/mpeg') {
            const audio = document.createElement('audio')
            let reader = new FileReader();
            reader.readAsDataURL(file);
            // console.log(file, 'file');
            reader.onload = function (e) {
              // console.log(e.target.result);
              audio.src = e.target.result;
              resolve();
            }
          } else {
            let options = {
              quality: 1, //输出的图像画质
              mimeType: isConversion ? "image/jpeg" : 'auto', //输出的文件类型
            }
            new Compressor(file, {
              ...options,
              // The compression process is asynchronous,
              // which means you have to access the `result` in the `success` hook function.
              success(result) {
                let nFile = new File([result], `${result.name}`, { type: result.type });
                let img = new Image();

                getBase(nFile).then((result) => {
                  img.src = result;
                })
                console.log(result)
                img.onload = async () => {
                  if (drawWaterMark) {
                    let fontSize = 33, fontFamily = "microsoft yahei", fontcolor = "#dadbdc", rotate = 30, textAlign = "left", density = 2.2

                    const canvas = document.createElement('canvas');
                    canvas.width = img.naturalWidth;
                    canvas.height = img.naturalHeight;
                    const ctx = canvas.getContext('2d');
                    ctx.drawImage(img, 0, 0);
                    ctx.fillStyle = fontcolor;
                    ctx.textBaseline = 'middle';
                    ctx.font = `${fontSize}px ${fontFamily}`;
                    ctx.lineWidth = 1;

                    let imgWidth = canvas.width;
                    let imgHeight = canvas.height;
                    //文字坐标
                    const maxPx = Math.max(imgWidth, imgHeight);
                    const stepPx = Math.floor(maxPx / density);
                    let arrayX = [0]; //初始水印位置 canvas坐标 0 0 点
                    while (arrayX[arrayX.length - 1] < maxPx / 2) {
                      arrayX.push(arrayX[arrayX.length - 1] + stepPx);
                    }
                    arrayX.push(
                      ...arrayX.slice(1, arrayX.length).map((el) => {
                        return -el;
                      })
                    );
                    for (let i = 0; i < arrayX.length; i++) {
                      for (let j = 0; j < arrayX.length; j++) {
                        ctx.save();
                        ctx.translate(imgWidth / 2, imgHeight / 2); ///画布旋转原点 移到 图片中心
                        ctx.rotate((Math.PI / 120) * -rotate);
                        let offsetY = fontSize * j + 2;
                        ctx.fillText(markText, arrayX[i], arrayX[j] + offsetY);
                        ctx.restore();
                      }
                    }
                    canvas.toBlob((result) => resolve(result));
                  }
                  else {
                    _that.checkImageDimensions(nFile, _that.props.imgWidth, _that.props.imgHeight).then(rrr => {
                      console.log(rrr, 'rrr');
                      resolve(nFile)

                    }).catch(errmsg => {
                      alert(errmsg)
                    })
                  }
                }
              },
              error(err) {
                // console.log(err.message);
                file.status = 'error'
                reject(new Error(err.message));
              },
            });

          }
        });
      } else {
        React.$message({
          type: 'info',
          content: `文件最大不能超过${(maxSize || 5)}M`
        })
        return false
      }
    };

    const RSnetToken = sessionStorage.getItem('RSnetToken')
    return (
      <>
        <Upload
          action={"/admin/oss/image/upload"}
          listType={type}
          fileList={fileList}
          accept={accept.toString()}
          data={data}
          headers={{ RSnetToken }}
          beforeUpload={checkFileSize}
          onPreview={this.handlePreview}
          previewFile={(e) => this.handlePreviewFile(e)}
          onRemove={this.handleRemove}
          onChange={this.handleChange}
          showUploadList={{ showRemoveIcon: isShowRemoveIcon }}>
          {(fileList.length >= len || disabled) ? null : uploadButton}
        </Upload>
        <Modal
          visible={previewVisible}
          title={previewTitle}
          footer={null}
          onCancel={this.handleCancel}>
          {
            previewType === 'img' && <img alt="example" style={{ width: '100%' }} src={previewImage} />
          }
          {
            previewType === 'video' && <video src={previewImage} style={{ width: '100%' }} controls></video>
          }
          {
            previewType === 'audio' && <audio src={previewImage} style={{ width: '100%' }} controls></audio>
          }
        </Modal>
      </>
    );
  }
}

TheUpload.propTypes = {
  disabled: PropTypes.bool,
  len: PropTypes.number,
  label: PropTypes.string,
  getFileResult: PropTypes.func,
  type: PropTypes.string,
  data: PropTypes.object,
  fileType: PropTypes.string,
  maxSize: PropTypes.number,
  imgWidth: PropTypes.number,
  imgHeight: PropTypes.number,
  mode: PropTypes.string,
  accept: PropTypes.array,
  isConversion: PropTypes.bool,
  isShowRemoveIcon: PropTypes.bool,
  fileList: PropTypes.array,
  drawWaterMark: PropTypes.bool,
  markText: PropTypes.string,
}
TheUpload.defaultProps = {
  disabled: false,
  len: 5,
  label: 'Upload',
  type: 'picture-card',
  data: {},
  fileType: 'image',
  maxSize: 5,
  accept: ['image/jpg', 'image/jpeg', 'image/png', 'image/webp', 'image/svg+xml', 'video/mp4', 'audio/x-m4a', 'audio/mpeg'],
  isConversion: false,
  isShowRemoveIcon: true,
  fileList: [],
  drawWaterMark: false,
  markText: ''
}
export default withRouter(TheUpload)
